// 内存存储实现，用于验证码和临时用户数据
// 注意：这是一个简单的内存存储实现，用于替代Redis
import crypto from 'crypto';

// 内存存储对象
const memoryStore = {};

/**
 * 设置带过期时间的键值对
 * @param {string} key - 键
 * @param {*} value - 值
 * @param {number} expiration - 过期时间（秒）
 */
function setWithExpiry(key, value, expiration) {
  // 存储值
  memoryStore[key] = {
    value,
    expiry: Date.now() + (expiration * 1000)
  };
  
  // 设置定时器自动清除过期数据
  setTimeout(() => {
    if (memoryStore[key] && memoryStore[key].expiry <= Date.now()) {
      delete memoryStore[key];
    }
  }, expiration * 1000);
}

/**
 * 获取键值对，如果已过期则返回null
 * @param {string} key - 键
 * @returns {*} 值或null
 */
function getWithExpiry(key) {
  const item = memoryStore[key];
  // 如果不存在或已过期，返回null
  if (!item || item.expiry <= Date.now()) {
    if (item) {
      delete memoryStore[key]; // 清理过期项目
    }
    return null;
  }
  return item.value;
}

// 模拟Redis客户端
const redisClient = {
  info: '内存存储模拟Redis客户端'
};

// 模拟连接函数
async function connectRedis() {
  console.log('使用内存存储替代Redis');
  return true;
}

/**
 * 存储验证码
 * @param {string} userId - 用户ID
 * @param {string} email - 用户邮箱
 * @param {string} code - 验证码
 * @param {number} expiresInSeconds - 过期时间（秒）
 * @returns {Promise<boolean>} 是否成功
 */
async function storeVerificationCode(userId, email, code, expiresInSeconds = 300) {
  try {
    const idKey = `verification_code:user:${userId}`;
    const emailKey = `verification_code:email:${email}`;
    
    // 存储验证码和发送时间
    setWithExpiry(idKey, code, expiresInSeconds);
    setWithExpiry(emailKey, code, expiresInSeconds);
    setWithExpiry(`${idKey}:sent_at`, Date.now().toString(), expiresInSeconds);
    
    console.log(`验证码已存储：用户ID ${userId}，邮箱 ${email}，有效期：${expiresInSeconds}秒`);
    return true;
  } catch (error) {
    console.error('存储验证码失败:', error);
    return false;
  }
}

/**
 * 获取验证码
 * @param {string} key - 用户ID或邮箱
 * @param {boolean} isEmail - 是否为邮箱
 * @returns {Promise<string|null>} 验证码或null
 */
async function getVerificationCode(key, isEmail = false) {
  try {
    const storeKey = isEmail 
      ? `verification_code:email:${key}`
      : `verification_code:user:${key}`;
    
    return getWithExpiry(storeKey);
  } catch (error) {
    console.error('获取验证码失败:', error);
    return null;
  }
}

/**
 * 获取验证码发送时间
 * @param {string} userId - 用户ID
 * @returns {Promise<number|null>} 时间戳或null
 */
async function getVerificationCodeSentTime(userId) {
  try {
    const sentTime = getWithExpiry(`verification_code:user:${userId}:sent_at`);
    return sentTime ? parseInt(sentTime) : null;
  } catch (error) {
    console.error('获取验证码发送时间失败:', error);
    return null;
  }
}

/**
 * 删除验证码
 * @param {string} userId - 用户ID
 * @param {string} email - 用户邮箱
 * @returns {Promise<boolean>} 是否成功
 */
async function deleteVerificationCode(userId, email) {
  try {
    const idKey = `verification_code:user:${userId}`;
    const emailKey = `verification_code:email:${email}`;
    
    delete memoryStore[idKey];
    delete memoryStore[emailKey];
    delete memoryStore[`${idKey}:sent_at`];
    
    return true;
  } catch (error) {
    console.error('删除验证码失败:', error);
    return false;
  }
}

/**
 * 检查是否可以发送新的验证码
 * @param {string} userId - 用户ID
 * @param {number} minIntervalSeconds - 最小等待时间（秒）
 * @returns {Promise<boolean>} 是否可以发送
 */
async function canSendNewVerificationCode(userId, minIntervalSeconds = 60) {
  try {
    const sentTime = await getVerificationCodeSentTime(userId);
    if (!sentTime) {
      return true;
    }
    
    const timeSinceLastSent = (Date.now() - sentTime) / 1000;
    return timeSinceLastSent >= minIntervalSeconds;
  } catch (error) {
    console.error('检查验证码发送间隔失败:', error);
    return false;
  }
}

/**
 * 获取剩余等待时间
 * @param {string} userId - 用户ID
 * @param {number} minIntervalSeconds - 最小等待时间（秒）
 * @returns {Promise<number>} 剩余等待时间（秒）
 */
async function getRemainingWaitTime(userId, minIntervalSeconds = 60) {
  try {
    const sentTime = await getVerificationCodeSentTime(userId);
    if (!sentTime) {
      return 0;
    }
    
    const timeSinceLastSent = (Date.now() - sentTime) / 1000;
    const remaining = minIntervalSeconds - timeSinceLastSent;
    return remaining > 0 ? Math.ceil(remaining) : 0;
  } catch (error) {
    console.error('计算剩余等待时间失败:', error);
    return 0;
  }
}

/**
 * 验证验证码是否有效
 * @param {string} userId - 用户ID
 * @param {string} email - 用户邮箱
 * @param {string} code - 用户提供的验证码
 * @returns {Promise<boolean>} 是否有效
 */
async function verifyCode(userId, email, code) {
  try {
    const storedCode = await getVerificationCode(userId);
    if (!storedCode) return false;
    
    // 验证码必须完全匹配
    const isValid = storedCode === code;
    
    // 如果验证成功，删除验证码以防止重复使用
    if (isValid) {
      await deleteVerificationCode(userId, email);
    }
    
    return isValid;
  } catch (error) {
    console.error('验证验证码失败:', error);
    return false;
  }
}

/**
 * 生成临时用户ID
 * @returns {string} 临时用户ID
 */
function generateTempUserId() {
  return crypto.randomBytes(16).toString('hex');
}

/**
 * 存储临时用户数据
 * @param {string} tempUserId - 临时用户ID
 * @param {object} userData - 用户数据
 * @param {number} expiresInSeconds - 过期时间（秒）
 * @returns {Promise<boolean>} 是否成功
 */
async function storeTempUserData(tempUserId, userData, expiresInSeconds = 300) {
  try {
    const key = `temp_user:${tempUserId}`;
    setWithExpiry(key, userData, expiresInSeconds);
    return true;
  } catch (error) {
    console.error('存储临时用户数据失败:', error);
    return false;
  }
}

/**
 * 获取临时用户数据
 * @param {string} tempUserId - 临时用户ID
 * @returns {Promise<object|null>} 用户数据或null
 */
async function getTempUserData(tempUserId) {
  try {
    const key = `temp_user:${tempUserId}`;
    const data = getWithExpiry(key);
    return data;
  } catch (error) {
    console.error('获取临时用户数据失败:', error);
    return null;
  }
}

/**
 * 删除临时用户数据
 * @param {string} tempUserId - 临时用户ID
 * @returns {Promise<boolean>} 是否成功
 */
async function deleteTempUserData(tempUserId) {
  try {
    const key = `temp_user:${tempUserId}`;
    delete memoryStore[key];
    return true;
  } catch (error) {
    console.error('删除临时用户数据失败:', error);
    return false;
  }
}

// 模拟关闭Redis连接
async function disconnectRedis() {
  console.log('内存存储已清除');
  Object.keys(memoryStore).forEach(key => delete memoryStore[key]);
}

export {
  redisClient,
  connectRedis,
  disconnectRedis,
  storeVerificationCode,
  getVerificationCode,
  getVerificationCodeSentTime,
  deleteVerificationCode,
  canSendNewVerificationCode,
  getRemainingWaitTime,
  verifyCode,
  generateTempUserId,
  storeTempUserData,
  getTempUserData,
  deleteTempUserData
};